package net.pinnoocle.playservice.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import net.pinnoocle.playcommon.constant.Constant;
import net.pinnoocle.playcommon.enums.UserTypeEnums;
import net.pinnoocle.playcommon.exception.ShopException;
import net.pinnoocle.playcommon.response.ErrorCode;
import net.pinnoocle.playcommon.utils.*;
import net.pinnoocle.playdao.dao.ShopUserStatisticsDao;
import net.pinnoocle.playdao.dao.UserDao;
import net.pinnoocle.playdao.entity.*;
import net.pinnoocle.playdao.entity.admin.InformListPageVo;
import net.pinnoocle.playdao.entity.admin.InformListSearchParams;
import net.pinnoocle.playdao.entity.page.PageModel;
import net.pinnoocle.playdao.entity.page.PageQuery;
import net.pinnoocle.playdao.entity.shopPc.user.*;
import net.pinnoocle.playdao.entity.web.master.MasterGroupListVo;
import net.pinnoocle.playdao.entity.web.order.UnPayOrderVo;
import net.pinnoocle.playdao.entity.web.user.*;
import net.pinnoocle.playdao.entity.web.user.homepage.*;
import net.pinnoocle.playservice.service.PayService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 用户表(User)表服务实现类
 *
 * @author ye
 * @since 2021-10-25 10:22:47
 */
@Service("userService")
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserDao, User> {

    @Autowired
    UserLevelServiceImpl userLevelService;
    @Autowired
    ShopUserServiceImpl shopUserService;
    @Autowired
    ScriptServiceImpl scriptService;
    @Autowired
    ShopServiceImpl shopService;
    @Autowired
    MasterServiceImpl masterService;
    @Autowired
    RoomServiceImpl roomService;
    @Autowired
    UserAppointOrderServiceImpl userAppointOrderService;
    @Autowired
    PayService payService;
    @Autowired
    UserServiceImpl userService;
    @Autowired
    UserGroupServiceImpl userGroupService;
    @Autowired
    OrderServiceImpl orderService;
    @Autowired
    UserCouponServiceImpl userCouponService;
    @Autowired
    GroupServiceImpl groupService;
    @Autowired
    UserScriptServiceImpl userScriptService;
    @Autowired
    InformServiceImpl informService;
    @Autowired
    MasterScriptServiceImpl masterScriptService;
    @Autowired
    ScriptEvaluateServiceImpl scriptEvaluateService;
    @Autowired
    ShopFinanceServiceImpl shopFinanceService;
    @Autowired
    WxServiceImpl wxService;
    @Autowired
    ShopStatisticsServiceImpl shopStatisticsService;

    /**
     * 会员列表
     * @param params
     * @return
     */
    public PageModel<UserListPageVo> shopUserList(UserListSearchParams params){
        Map<String,Object> pageMap = new HashMap<>();
        pageMap.put("page",String.valueOf(params.getPage()));
        pageMap.put("pageSize",String.valueOf(params.getPageSize()));

        if(params.getShopId() == null){
            String shopId = shopService.getShopId();
            params.setShopId(shopId);
        }
        Integer expenseType = params.getExpenseType();
        if(expenseType != null){
            HashMap<String, String> startAndEndDate = HelpUtils.getStartAndEndDate(expenseType);
            params.setExpenseStartDate(startAndEndDate.get("startDate"));
            params.setExpenseEndDate(startAndEndDate.get("endDate"));
        }
        Page<UserListPageVo> list = this.baseMapper.shopUserList(
                new PageQuery<ShopUser>(pageMap).getPage(),params);
        List<UserListPageVo> records = list.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            return new PageModel<>(list, new ArrayList<>());
        }
        return new PageModel<>(list, records);
    }

    /**
     * 店铺会员等级列表
     * @return
     */
    public List<UserLevelListVo> userLevelList(){
        String userId = JwtUtil.getUserId();
        if(StringUtils.isBlank(userId)){
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"登录信息获取失败");
        }
        List<UserLevel> userLevels = userLevelService.list(new QueryWrapper<UserLevel>()
                .lambda()
                .eq(UserLevel::getShopId, userId));
        return ConvertUtils.sourceToTarget(userLevels, UserLevelListVo.class);
    }

    /**
     * 用户登录
     * @param wechatUserInfo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public LoginResultVo userLogin_old(WechatUserInfo wechatUserInfo){
        LoginResultVo resultVo = new LoginResultVo();
        Integer shopWechatId = JwtUtil.getShopWechatId();
        String code = wechatUserInfo.getCode();
        String inviterId = wechatUserInfo.getInviterId() != null ? wechatUserInfo.getInviterId() : "";
        String sourceName = wechatUserInfo.getSourceName() != null ? wechatUserInfo.getSourceName() : "";
        ShopWechatSetting shopWechatSetting = this.baseMapper.shopWechatSetting(shopWechatId);
        if(Objects.isNull(shopWechatSetting)){
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"小程序未配置，登录失败");
        }
        String shopId = shopWechatSetting.getShopId();
        try {
            String appId = shopWechatSetting.getAppId();
            String secret = shopWechatSetting.getAppSecret();
            JSONObject jsonObject = WechatUtils.wechatLogin(appId,secret,code);
            // 授权失败
            if(jsonObject.containsKey("errcode") && jsonObject.getInteger("errcode") > 0){
                Integer errCode = jsonObject.getInteger("errcode");
                String errorMsg = jsonObject.getString("errmsg");
                resultVo.setErrorCode(errCode);
                resultVo.setErrorMsg(errorMsg);
            }else{
                String openId = jsonObject.getString("openid");
                String sessionKey = jsonObject.getString("session_key");
                String unionId = jsonObject.containsKey("unionid") ? jsonObject.getString("unionid") : "";
                User userInfo = this.getOne(new QueryWrapper<User>()
                        .lambda()
                        .eq(User::getOpenId, openId));
                //第一次登录
                User user = new User();
                if(Objects.isNull(userInfo)){
                    String userId = HelpUtils.get24UUID();
                    String userNo = HelpUtils.getRandomNumber();
                    user.setUserId(userId);
                    user.setUserNo(userNo);
                    user.setOpenId(openId);
                    user.setSessionKey(sessionKey);
                    user.setUnionId(unionId);
                    user.setWxName(wechatUserInfo.getNickName());
                    user.setGender(wechatUserInfo.getGender());
                    user.setHeadPortrait(wechatUserInfo.getAvatarUrl());
                    user.setLoginTime(new Date());
                    user.setCreatedTime(new Date());
                    boolean result = this.save(user);
                    if(result){
                        HashMap<String, Object> shopUserMap = new HashMap<>();
                        shopUserMap.put("shopId",shopId);
                        shopUserMap.put("userId",userId);
                        shopUserMap.put("inviterId",inviterId);
                        shopUserMap.put("sourceName",sourceName);
                        syncShopUser(shopUserMap);
                        resultVo.setShopId(shopId);
                        resultVo.setUserId(userId);
                        resultVo.setUserNo(userNo);
                        resultVo.setErrorCode(0);
                        resultVo.setToken(JwtUtil.createToken(userId,wechatUserInfo.getNickName(),shopId));
                    }
                }else{
                    user.setUserId(wechatUserInfo.getUserId());
                    user.setWxName(wechatUserInfo.getNickName());
                    user.setGender(wechatUserInfo.getGender());
                    user.setHeadPortrait(wechatUserInfo.getAvatarUrl());
                    user.setLoginTime(new Date());
                    this.updateById(user);
                    resultVo.setShopId(shopId);
                    resultVo.setUserId(userInfo.getUserId());
                    resultVo.setUserNo(userInfo.getUserNo());
                    resultVo.setMobile(userInfo.getMobile());
                    resultVo.setErrorCode(0);
                    resultVo.setToken(JwtUtil.createToken(userInfo.getUserId(),user.getWxName(),shopId));
                }
            }
        } catch (ShopException e) {
            log.info("用户授权失败："+e.getMessage());
        }
        return resultVo;
    }

    /**
     * 第三方平台代登录
     * @param wechatUserInfo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public LoginResultVo userLogin(WechatUserInfo wechatUserInfo){
        LoginResultVo resultVo = new LoginResultVo();
        Integer shopWechatId = JwtUtil.getShopWechatId();
        String code = wechatUserInfo.getCode();
        String inviterId = wechatUserInfo.getInviterId() != null ? wechatUserInfo.getInviterId() : "";
        String sourceName = wechatUserInfo.getSourceName() != null ? wechatUserInfo.getSourceName() : "";
        ShopWechatSetting shopWechatSetting = this.baseMapper.shopWechatSetting(shopWechatId);
        if(Objects.isNull(shopWechatSetting)){
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"小程序未配置，登录失败");
        }
        String shopId = shopWechatSetting.getShopId();
        try {
            String appId = shopWechatSetting.getAppId();
            String componentAccessToken = wxService.getComponentAccessToken();
            JSONObject jsonObject = WechatUtils.wechatLoginThird(appId,code,componentAccessToken);
            // 授权失败
            if(jsonObject.containsKey("errcode") && jsonObject.getInteger("errcode") > 0){
                Integer errCode = jsonObject.getInteger("errcode");
                String errorMsg = jsonObject.getString("errmsg");
                resultVo.setErrorCode(errCode);
                resultVo.setErrorMsg(errorMsg);
            }else{
                String openId = jsonObject.getString("openid");
                String sessionKey = jsonObject.getString("session_key");
                String unionId = jsonObject.containsKey("unionid") ? jsonObject.getString("unionid") : "";
                User userInfo = this.getOne(new QueryWrapper<User>()
                        .lambda()
                        .eq(User::getOpenId, openId));
                //第一次登录
                User user = new User();
                if(Objects.isNull(userInfo)){
                    String userId = HelpUtils.get24UUID();
                    String userNo = HelpUtils.getRandomNumber();
                    user.setUserId(userId);
                    user.setUserNo(userNo);
                    user.setOpenId(openId);
                    user.setSessionKey(sessionKey);
                    user.setUnionId(unionId);
                    user.setWxName(wechatUserInfo.getNickName());
                    user.setGender(wechatUserInfo.getGender());
                    user.setHeadPortrait(wechatUserInfo.getAvatarUrl());
                    user.setLoginTime(new Date());
                    user.setCreatedTime(new Date());
                    boolean result = this.save(user);
                    if(result){
                        HashMap<String, Object> shopUserMap = new HashMap<>();
                        shopUserMap.put("shopId",shopId);
                        shopUserMap.put("userId",userId);
                        shopUserMap.put("inviterId",inviterId);
                        shopUserMap.put("sourceName",sourceName);
                        syncShopUser(shopUserMap);
                        resultVo.setShopId(shopId);
                        resultVo.setUserId(userId);
                        resultVo.setUserNo(userNo);
                        resultVo.setErrorCode(0);
                        resultVo.setToken(JwtUtil.createToken(userId,wechatUserInfo.getNickName(),shopId));
                        //第一次登录，访客数和浏览量+1
                        shopStatisticsService.grandShopStatisticsVisit(shopId,true,true);
                    }
                }else{
                    user.setUserId(wechatUserInfo.getUserId());
                    user.setWxName(wechatUserInfo.getNickName());
                    user.setGender(wechatUserInfo.getGender());
                    user.setHeadPortrait(wechatUserInfo.getAvatarUrl());
                    user.setLoginTime(new Date());
                    this.updateById(user);
                    resultVo.setShopId(shopId);
                    resultVo.setUserId(userInfo.getUserId());
                    resultVo.setUserNo(userInfo.getUserNo());
                    resultVo.setMobile(userInfo.getMobile());
                    resultVo.setErrorCode(0);
                    resultVo.setToken(JwtUtil.createToken(userInfo.getUserId(),user.getWxName(),shopId));
                    Date loginTime = userInfo.getLoginTime();
                    //上次登录在昨天，今天登录访客数累加
                    boolean yesterday = HelpUtils.isYesterday(loginTime);
                    shopStatisticsService.grandShopStatisticsVisit(shopId,yesterday,false);
                }
            }
        } catch (ShopException e) {
            log.info("用户授权失败："+e.getMessage());
        }
        return resultVo;
    }

    /**
     * 解密微信授权手机号
     * @param wechatEncryptData
     * @return
     */
    public String encryptWechatPhone(WechatEncryptData wechatEncryptData){
        Integer shopWechatId = JwtUtil.getShopWechatId();
        String code = wechatEncryptData.getCode();
        ShopWechatSetting shopWechatSetting = this.baseMapper.shopWechatSetting(shopWechatId);
        if(Objects.isNull(shopWechatSetting)){
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"小程序未配置，授权失败");
        }
        String appId = shopWechatSetting.getAppId();
        String componentAccessToken = wxService.getComponentAccessToken();
        JSONObject jsonObject = WechatUtils.wechatLoginThird(appId,code,componentAccessToken);
        if(jsonObject.containsKey("errcode") && jsonObject.getInteger("errcode") > 0){
            log.info("授权失败==={}",JSONObject.toJSONString(jsonObject));
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"授权失败");
        }
        String sessionKey = jsonObject.getString("session_key");
        String openId = jsonObject.getString("openid");
        String resultJson = WechatDecryptDataUtil.decryptData(wechatEncryptData.getEncryptedData(),
                sessionKey, wechatEncryptData.getIv());
        JSONObject data = JSON.parseObject(resultJson);
        if(data.containsKey("purePhoneNumber")){
            String phone = data.getString("purePhoneNumber");
            User user = new User();
            user.setMobile(phone);
            boolean result = this.update(user, new QueryWrapper<User>()
                    .lambda()
                    .eq(User::getOpenId, openId));
            if(!result){
                throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"手机号保存失败");
            }
            return data.getString("purePhoneNumber");
        }
        throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"获取手机号失败");
    }

    /**
     * 通过授权token获取用户id
     * @return
     */
    public String getUserId(){
        return JwtUtil.getUserId();
    }

    /**
     * token获取主持人id
     * @return
     */
    public String getMasterId(){
        String userId = JwtUtil.getUserId();
        String shopId = shopService.getShopId();
        Master master = masterService.getOne(new QueryWrapper<Master>()
                .lambda()
                .eq(Master::getShopId, shopId)
                .eq(Master::getUserId, userId));
        return Objects.nonNull(master) ? master.getMasterId() : "";
    }

    /**
     * web端通知列表
     * @return
     */
    public PageModel<InformListPageVo> informListWithWeb(){
        String shopId = userService.getGlobalShopId();
        InformListSearchParams informListSearchParams = new InformListSearchParams();
        informListSearchParams.setType(1);
        informListSearchParams.setShopId(shopId);
        return informService.informList(informListSearchParams);
    }

    /**
     * 首页数据
     * @return
     */
    public HomePageVo homePage(){
        HomePageVo homePageVo = new HomePageVo();
        String shopId = userService.getGlobalShopId();
        //店铺信息
        ShopInfoVo shopInfoVo = shopService.homePageShopInfo(shopId);
        if(Objects.isNull(shopInfoVo)){
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"店铺不存在，登录失败");
        }
        homePageVo.setShopInfoVo(shopInfoVo);
        //推荐组局
        RecommendGroupVo oneCar = groupService.getOneCar(shopId);
        homePageVo.setGroupVo(oneCar);
        //最新剧本
        Script script = scriptService.getOne(new QueryWrapper<Script>()
                .lambda()
                .eq(Script::getShopId, shopId)
                .eq(Script::getIsDisable, 0)
                .orderByDesc(Script::getCreatedTime)
                .last("LIMIT 1"));
        NewScriptVo newScriptVo = ConvertUtils.sourceToTarget(script, NewScriptVo.class);
        //获取剧本内容
        String scriptContent = scriptService.getScriptContent(script.getScriptId());
        newScriptVo.setContent(scriptContent);
        homePageVo.setScriptVo(newScriptVo);
        //推荐剧本
        List<Script> list = scriptService.list(new QueryWrapper<Script>()
                .lambda()
                .eq(Script::getShopId, shopId)
                .eq(Script::getIsDisable, 0)
                .orderByAsc(Script::getSort)
                .last("LIMIT " + Constant.HOMEPAGE_PAGE_SIZE));
        List<RecommendScriptVo> recommendScriptVos = ConvertUtils.sourceToTarget(list, RecommendScriptVo.class);
        homePageVo.setRecommendScriptVo(recommendScriptVos);
        //本地DM
        List<Master> masterList = masterService.list(new QueryWrapper<Master>()
                .lambda()
                .eq(Master::getShopId, shopId)
                .eq(Master::getIsCheck, 1)
                .eq(Master::getJobStatus, 0)
                .eq(Master::getIsHot, 1)
                .orderByAsc(Master::getTotalDmTimes).last("LIMIT " + Constant.HOMEPAGE_PAGE_SIZE));
        List<RecommendMasterVo> recommendMasterVos = ConvertUtils.sourceToTarget(masterList, RecommendMasterVo.class);
        homePageVo.setMasterVo(recommendMasterVos);
        //推荐房间
        List<Room> rooms = roomService.list(new QueryWrapper<Room>()
                .lambda()
                .eq(Room::getShopId, shopId)
                .orderByDesc(Room::getCreatedTime)
                .last("LIMIT " + Constant.HOMEPAGE_PAGE_SIZE));
        List<RoomInfoVo> roomInfoVos = ConvertUtils.sourceToTarget(rooms, RoomInfoVo.class);
        homePageVo.setRoomInfoVo(roomInfoVos);
        return homePageVo;
    }

    /**
     * 用户个人中心
     * @return
     */
    public UserCenterPageVo centerPage(){
        String userId = this.getUserId();
        ShopUserCombination shopUserCombination = shopUserDetail(userId);
        String shopId = shopUserCombination.getShopId();
        int memberLevelId = shopUserCombination.getMemberLevelId();
        //用户类型
        Integer roleType = roleTypeByPhone(shopUserCombination );
        UserCenterPageVo userCenterPageVo = ConvertUtils.sourceToTarget(shopUserCombination, UserCenterPageVo.class);
        userCenterPageVo.setRoleType(roleType);
        //会员等级
        UserLevel userLevel = userLevelService.getById(memberLevelId);
        if(Objects.nonNull(userLevel)){
            userCenterPageVo.setMemberLevelName(userLevel.getLevelName());
            userCenterPageVo.setMemberLevelIcon(userLevel.getIconPath());
        }
        //获取上级会员级别信息
        UserLevel upOneLevel = this.baseMapper.upOneLevel(shopId, shopUserCombination.getPlayTimes());
        if(Objects.nonNull(upOneLevel)){
            String memberNotice = "距离成为"+upOneLevel.getLevelName()+"还有"
                    +(upOneLevel.getAutoUpgrade()-shopUserCombination.getPlayTimes())+"次";
            userCenterPageVo.setMemberNotice(memberNotice);
        }
        int count = userCouponService.count(new QueryWrapper<UserCoupon>().lambda()
                .eq(UserCoupon::getUserId, userId)
                .eq(UserCoupon::getStatus, 0)
                .ne(UserCoupon::getEffectStatus, 2));
        userCenterPageVo.setCouponNum(count);
        //DM审核状态
        Master master = masterService.getOne(new QueryWrapper<Master>()
                .lambda()
                .eq(Master::getShopId, shopId)
                .eq(Master::getUserId, userId));
        if(Objects.isNull(master)){
            userCenterPageVo.setDmCheckStatus(0);
        }else if(master.getIsCheck() == 0){
            userCenterPageVo.setDmCheckStatus(1);
        }else if(master.getIsCheck() == 2){
            userCenterPageVo.setDmCheckStatus(2);
        }
        return userCenterPageVo;
    }

    /**
     * 判断用户类型
     * @param shopUserCombination
     * @return
     */
    private Integer roleTypeByPhone(ShopUserCombination shopUserCombination){
        String shopId = shopUserCombination.getShopId();
        String phone = shopUserCombination.getMobile();
        String userId = shopUserCombination.getUserId();
        Master master = masterService.getOne(new QueryWrapper<Master>()
                .lambda()
                .eq(Master::getShopId, shopId)
                .eq(Master::getUserId, userId)
                .eq(Master::getJobStatus, 0)
                .eq(Master::getIsCheck, 1));
        if(Objects.nonNull(master)){
            return UserTypeEnums.MASTER.getStatus();              
        }
        Shop shop = shopService.getOne(new QueryWrapper<Shop>()
                .lambda()
                .eq(Shop::getShopId, shopId)
                .eq(Shop::getMobile, phone)
                .eq(Shop::getIsDisable, 0));
        if(Objects.nonNull(shop)){
            return UserTypeEnums.SHOP.getStatus();
        }
        return UserTypeEnums.USER.getStatus();
    }

    /**
     * 用户详情
     * @param userId
     * @return
     */
    public ShopUserCombination shopUserDetail(String userId){
        return this.baseMapper.shopUserDetail(userId);
    }

    /**
     * 获取店铺小程序配置
     * @param shopWechatId
     * @return
     */
    public ShopWechatSetting getShopWechatSetting(Integer shopWechatId){
        return this.baseMapper.shopWechatSetting(shopWechatId);
    }

    /**
     * 申请成为DM
     * @param params
     * @return
     */
    public boolean applyMaster(ApplyMasterParams params){
        String userId = this.getUserId();
        User userInfo = this.getById(userId);
        if(Objects.isNull(userInfo)){
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"登录信息获取失败");
        }
        List<String> scriptIds = params.getScriptIds();
        if(CollectionUtils.isEmpty(scriptIds)){
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"请选择至少1个剧本");
        }
        String shopId = userService.getGlobalShopId();
        Master masterExists = masterService.getOne(new QueryWrapper<Master>()
                .lambda()
                .eq(Master::getShopId, shopId)
                .eq(Master::getUserId, userId),false);
        try {
            Master master = ConvertUtils.sourceToTarget(params, Master.class);
            master.setMobile(userInfo.getMobile());
            master.setUserId(userId);
            master.setHeadPortrait(userInfo.getHeadPortrait());
            master.setCreatedTime(new Date());
            master.setShopId(shopId);
            int age = HelpUtils.getAgeByBirth(params.getBirthday());
            master.setAge(age);
            master.setScriptNum(scriptIds.size());
            master.setJobStatus(0);
            master.setIsCheck(0);
            boolean result = false;
            if(Objects.nonNull(masterExists)){
                master.setMasterId(masterExists.getMasterId());
                result = masterService.updateById(master);
            }else{
                result = masterService.save(master);
            }
            if(result){
                masterScriptService.addMasterScripts(master.getMasterId(),shopId,scriptIds);
            }
            return result;
        } catch (Exception e) {
            log.info("申请DM失败："+e.getMessage());
        }
        return false;
    }

    /**
     * 定金去支付
     * @param orderId
     * @return
     */
    public PayInfo appointAmountPay(String orderId) throws Exception {
        UserAppointOrder orderInfo = userAppointOrderService.getById(orderId);
        if(Objects.isNull(orderInfo)){
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"订单不存在");
        }
        if(orderInfo.getHasPay() == 1){
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"该订单已支付，请勿重复支付");
        }
        User user = userService.getById(orderInfo.getUserId());
        if(Objects.isNull(user)){
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"支付异常");
        }
        PayInfo payInfo = payService.payOrder(orderInfo.getShopId(), user.getOpenId(), orderInfo.getPayAmount(),1);
        if(Objects.nonNull(payInfo)){
            orderInfo.setOutTradeNo(payInfo.getOutTradeNo());
            boolean result = userAppointOrderService.updateById(orderInfo);
            if(!result){
                return null;
            }
        }
        return payInfo;
    }

    /**
     * 订单支付状态查询
     * @param orderId
     * @return
     * @throws Exception
     */
    public String appointOrderQuery(String orderId) throws Exception {
        UserAppointOrder orderInfo = userAppointOrderService.getById(orderId);
        if(orderInfo.getHasPay() == 1){
            return "success";
        }
        OrderInfoVo orderInfoVo = payService.orderQuery(orderInfo.getOutTradeNo());
        String tradeState = orderInfoVo.getTradeState();
        if(Objects.equals(tradeState, "SUCCESS")){
            try {
                orderInfo.setHasPay(1);
                orderInfo.setPayTime(orderInfoVo.getPayTime());
                orderInfo.setTransactionId(orderInfoVo.getTransactionId());
                userAppointOrderService.updateById(orderInfo);
                groupService.joinGroupDo(orderInfo.getGroupId(),orderInfo.getUserId());
                ShopFinance shopFinance = new ShopFinance();
                shopFinance.setShopId(orderInfo.getShopId());
                shopFinance.setAmount(orderInfo.getPayAmount());
                shopFinance.setFinanceType(0);
                shopFinance.setSourceName("支付定金");
                shopFinance.setOrderNo(orderInfo.getOrderNo());
                shopFinance.setCreatedTime(new Date());
                shopFinanceService.save(shopFinance);
                return "success";
            } catch (Exception e) {
                log.info("appointOrderQuery=="+e.getMessage());
            }
        }
        return "fail";
    }

    /**
     * 未支付订单
     * @return
     */
    public UnPayOrderVo unPayOrder(){
        String userId = userService.getUserId();
        UserGroup userGroup = userGroupService.getOne(new QueryWrapper<UserGroup>()
                .lambda()
                .eq(UserGroup::getUserId, userId)
                .eq(UserGroup::getIsPay, 0),false);
        if(Objects.isNull(userGroup)){
            return null;
        }
        Script script = scriptService.getById(userGroup.getScriptId());
        if(Objects.isNull(script)){
            return null;
        }
        UnPayOrderVo unPayOrderVo = ConvertUtils.sourceToTarget(script, UnPayOrderVo.class);
        //未支付的订单（有且只有一条）
        Order order = orderService.getOne(new QueryWrapper<Order>()
                .lambda()
                .select(Order::getPayPrice,Order::getOrderId)
                .eq(Order::getUserId, userId)
                .eq(Order::getHasPay, 0),false);
        if(Objects.isNull(order)){
            return null;
        }
        String userCouponId = order.getUserCouponId();
        UserCoupon userCoupon = userCouponService.getById(userCouponId);
        //使用了优惠券并且优惠券过期了
        if(Objects.nonNull(userCoupon) && userCoupon.getEffectStatus() == 2){
            unPayOrderVo.setCouponExpired(1);
            double newPryPrice = BigDecimalMathUtil.add(order.getPayPrice(), order.getDiscountPrice());
            order.setPayPrice(newPryPrice);
        }
        String cateNames = scriptService.getNamesByIds(script.getScriptCateId(), 0);
        unPayOrderVo.setScriptCateName(cateNames);
        unPayOrderVo.setPayPrice(order.getPayPrice());
        unPayOrderVo.setOrderId(order.getOrderId());
        return unPayOrderVo;
    }

    /**
     * 订单重新发起支付
     * @param orderId
     * @return
     */
    public PayInfo unPayOrderGoPay(String orderId) throws Exception {
        return orderService.billGoPay(orderId);
    }

    /**
     * 我玩过的本或我想玩的本
     * @param userId
     * @param page
     * @param pageSize
     * @param type
     * @return
     */
    public PageModel<UserScriptListPageVo> myScripts(String userId,Integer page, Integer pageSize, Integer type){
        Map<String,Object> pageMap = new HashMap<>();
        pageMap.put("page",String.valueOf(page));
        pageMap.put("pageSize",String.valueOf(pageSize));

        Page<UserScriptListPageVo> list = this.baseMapper.myScripts(
                new PageQuery<UserScript>(pageMap).getPage(),userId,type);
        List<UserScriptListPageVo> records = list.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            return new PageModel<>(list, new ArrayList<>());
        }
        for (UserScriptListPageVo item : records){
            String cateNames = scriptService.getNamesByIds(item.getScriptCateId(), 0);
            String levelNames = scriptService.getNamesByIds(item.getScriptCateId(), 1);
            item.setScriptCateName(cateNames);
            item.setScriptLevelName(levelNames);
        }
        return new PageModel<>(list, records);
    }


    /**
     * 收藏剧本
     * @param scriptId
     * @return
     */
    public String collectScript(String scriptId){
        Script script = scriptService.getById(scriptId);
        if(Objects.isNull(script)){
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"剧本不存在");
        }
        String userId = this.getUserId();
        try {
            UserScript userScriptExists = userScriptService.getOne(new QueryWrapper<UserScript>()
                    .lambda()
                    .eq(UserScript::getUserId, userId)
                    .eq(UserScript::getType, 1)
                    .eq(UserScript::getScriptId, scriptId), false);
            boolean result;
            String message;
            if(Objects.nonNull(userScriptExists)){
                result = userScriptService.removeById(userScriptExists.getUserScriptId());
                script.setWantNum(script.getWantNum()-1);
                message = "取消收藏成功";
            }else{
                UserScript userScript = new UserScript();
                userScript.setScriptId(scriptId);
                userScript.setUserId(userId);
                userScript.setShopId(script.getShopId());
                userScript.setType(1);
                userScript.setCreatedTime(new Date());
                result = userScriptService.save(userScript);
                script.setWantNum(script.getWantNum()+1);
                message = "收藏成功";
            }
            if(result){
                scriptService.updateById(script);
                return message;
            }
        } catch (Exception e) {
            log.info("收藏剧本失败："+e.getMessage());
        }
        return "";
    }

    /**
     * 我玩过的本
     * @param scriptId
     * @return
     */
    public boolean playScript(String scriptId){
        String userId = userService.getUserId();
        UserScript userScriptOne = userScriptService.getOne(new QueryWrapper<UserScript>().lambda()
                .eq(UserScript::getScriptId, scriptId)
                .eq(UserScript::getUserId, userId)
                .eq(UserScript::getType, 0),false);
        if(Objects.nonNull(userScriptOne)){
            return true;
        }
        Script script = scriptService.getById(scriptId);
        try {
            UserScript userScript = new UserScript();
            userScript.setScriptId(script.getScriptId());
            userScript.setShopId(script.getShopId());
            userScript.setUserId(userId);
            userScript.setType(0);
            userScript.setCreatedTime(new Date());
            boolean result = userScriptService.save(userScript);
            if(result){
                script.setPlayNum(script.getPlayNum()+1);
                return scriptService.updateById(script);
            }
        } catch (Exception e) {
            log.info("设置失败："+e.getMessage());
        }
        return false;
    }

    /**
     * 用户排行榜
     * @param page
     * @param pageSize
     * @return
     */
    public PageModel<SimpleUserInfoVo> topUserList(Integer page,Integer pageSize){
        Map<String,Object> pageMap = new HashMap<>();
        pageMap.put("page",String.valueOf(page));
        pageMap.put("pageSize",String.valueOf(pageSize));

        String shopId = userService.getGlobalShopId();
        Page<SimpleUserInfoVo> list = this.baseMapper.topUserList(
                new PageQuery<User>(pageMap).getPage(),shopId);
        List<SimpleUserInfoVo> records = list.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            return new PageModel<>(list, new ArrayList<>());
        }
        return new PageModel<>(list, records);
    }

    /**
     * 玩本结束更新用户信息
     * @param userId
     * @param scriptTime
     * @param payAmount
     * @param memberLevelId
     * @return
     */
    public boolean updateShopUser(String userId,Double scriptTime,Double payAmount,Integer memberLevelId){
        return this.baseMapper.updateShopUser(userId,scriptTime,payAmount,memberLevelId);
    }

    /**
     * 获取用户已经玩了多少次
     * @param userId
     * @return
     */
    public int getUserPlayTimes(String userId){
        return this.baseMapper.getUserPlayTimes(userId);
    }

    /**
     * 用户关于剧本的信息
     * @param scriptId
     * @return
     */
    public UserDetailVo userScriptDetail(String scriptId){
        String userId = userService.getUserId();
        int playCount = userScriptService.count(new QueryWrapper<UserScript>()
                .lambda()
                .eq(UserScript::getUserId, userId)
                .eq(UserScript::getScriptId, scriptId)
                .eq(UserScript::getType,0));
        int wantCount = userScriptService.count(new QueryWrapper<UserScript>()
                .lambda()
                .eq(UserScript::getUserId, userId)
                .eq(UserScript::getScriptId, scriptId)
                .eq(UserScript::getType,1));
        ScriptEvaluate evaluate = scriptEvaluateService.getOne(new QueryWrapper<ScriptEvaluate>().lambda()
                .eq(ScriptEvaluate::getUserId, userId)
                .eq(ScriptEvaluate::getScriptId, scriptId), false);
        UserDetailVo userDetailVo = new UserDetailVo();
        if(Objects.nonNull(evaluate)){
            userDetailVo.setStarNum(evaluate.getStarNum());
        }
        userDetailVo.setIsPlay(playCount > 0 ? 1 : 0);
        userDetailVo.setIsCollect(wantCount > 0 ? 1 :0);
        return userDetailVo;
    }

    /**
     * 通过店铺标识获取店铺id
     * @return
     */
    public String getGlobalShopId(){
        Integer shopWechatId = JwtUtil.getShopWechatId();
        if(shopWechatId == null){
            return shopService.getShopId();
        }
        ShopWechatSetting shopWechatSetting = this.baseMapper.shopWechatSetting(shopWechatId);
        if(Objects.isNull(shopWechatSetting)){
            throw new ShopException(ErrorCode.TOKEN_INVALID,"小程序未配置，登录失败");
        }
        return shopWechatSetting.getShopId();
    }

    /**
     * 我的组局
     * @param params
     * @return
     */
    public PageModel<MasterGroupListVo> myGroupList(MyGroupListSearchParams params){
        Map<String,Object> pageMap = new HashMap<>();
        pageMap.put("page",String.valueOf(params.getPage()));
        pageMap.put("pageSize",String.valueOf(params.getPageSize()));

        String userId = userService.getUserId();
        params.setUserId(userId);
        Page<MasterGroupListVo> list = this.baseMapper.myGroupList(
                new PageQuery<UserGroup>(pageMap).getPage(),params);
        List<MasterGroupListVo> records = list.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            return new PageModel<>(list, new ArrayList<>());
        }
        for (MasterGroupListVo item : records){
            String cateNames = scriptService.getNamesByIds(item.getScriptCateId(), 0);
            item.setScriptCateName(cateNames);
        }
        return new PageModel<>(list, records);
    }

    /**
     * 同步门店用户表信息
     * @param shopUserMap
     * @return
     */
    private boolean syncShopUser(Map<String,Object> shopUserMap){
        ShopUser shopUser = new ShopUser();
        String shopId = (String) shopUserMap.get("shopId");
        String userId = (String) shopUserMap.get("userId");
        String inviterId = (String) shopUserMap.get("inviterId");
        String sourceName = (String) shopUserMap.get("sourceName");
        shopUser.setShopId(shopId);
        shopUser.setUserId(userId);
        shopUser.setInviterId(inviterId);
        shopUser.setSourceName(sourceName);
        if(StringUtils.isNotBlank(inviterId)){
            User userData = this.getById(inviterId);
            if(Objects.nonNull(userData)){
                shopUser.setInviterName(userData.getWxName());
            }
        }
        /*UserLevel userLevel = userLevelService.getOne(new QueryWrapper<UserLevel>()
                .lambda()
                .eq(UserLevel::getShopId, shopId)
                .orderByAsc(UserLevel::getAutoUpgrade));
        if(Objects.nonNull(userLevel)){
            shopUser.setMemberLevelId(userLevel.getLevelId());
        }*/
        shopUser.setCreatedTime(new Date());
        return shopUserService.save(shopUser);
    }

    /**
     * 设置会员等级
     * @param userId
     * @param memberLevelId
     * @return
     */
    public boolean setUserMemberLevel(String userId,Integer memberLevelId){
        String shopId = userService.getGlobalShopId();
        ShopUser shopUser = shopUserService.getOne(new QueryWrapper<ShopUser>()
                .lambda()
                .eq(ShopUser::getUserId, userId)
                .eq(ShopUser::getShopId, shopId), false);
        if(Objects.isNull(shopUser)){
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"会员不存在");
        }
        UserLevel userLevel = userLevelService.getById(memberLevelId);
        if(Objects.isNull(userLevel)){
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"会员等级不存在");
        }
        try {
            shopUser.setMemberLevelId(memberLevelId);
            return shopUserService.updateById(shopUser);
        } catch (Exception e) {
            log.info("会员等级设置失败："+e.getMessage());
        }
        return false;
    }

    /**
     * 门店玩家排行
     * @return
     */
    public List<TopUserListVo> topFiveUserList(){
        String shopId = userService.getGlobalShopId();
        List<TopUserListVo> topUserListVos = this.baseMapper.topFiveUserList(shopId,Constant.TOP_NUM);
        if(CollectionUtils.isEmpty(topUserListVos)){
            return new ArrayList<>();
        }
        return topUserListVos;
    }

    /**
     * 获取一张用户的满减优惠券
     * @param userId
     * @return
     */
    public UserCoupon autoGetOneUserCoupon(String userId,Double payPrice){
        return userCouponService.getOne(new QueryWrapper<UserCoupon>()
                .lambda()
                .eq(UserCoupon::getUserId, userId)
                .le(UserCoupon::getFullValue, payPrice)
                .eq(UserCoupon::getStatus, 0)
                .eq(UserCoupon::getEffectStatus, 1)
                .orderByDesc(UserCoupon::getFaceValue).last("Limit 1"));
    }

    /**
     * 设置用户为主持人
     * @param userId
     * @return
     */
    public boolean setUserToMaster(String userId){
        String shopId = userService.getGlobalShopId();
        Master masterOne = masterService.getOne(new QueryWrapper<Master>()
                .lambda()
                .eq(Master::getShopId,shopId)
                .eq(Master::getUserId, userId), false);
        if(Objects.nonNull(masterOne)){
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"该用户已经是主持人");
        }
        try {
            User userInfo = this.getById(userId);
            Master master = new Master();
            master.setShopId(shopId);
            master.setUserId(userId);
            master.setNickName(userInfo.getWxName());
            master.setMobile(userInfo.getMobile());
            master.setHeadPortrait(userInfo.getHeadPortrait());
            master.setGender(userInfo.getGender());
            master.setIsCheck(1);
            master.setCreatedTime(new Date());
            return masterService.save(master);
        } catch (Exception e) {
            log.info("设置主持人失败："+e.getMessage());
        }
        return false;
    }

    /**
     * 统计累计用户
     * @param shopId
     * @param dateTime
     * @return
     */
    public int countUserByDate(String shopId,String dateTime){
        return this.baseMapper.countUserByDate(shopId,dateTime);
    }

    /**
     * 统计累计付费用户
     * @param shopId
     * @param dateTime
     * @return
     */
    public int countPayUserByDate(String shopId,String dateTime){
        return this.baseMapper.countPayUserByDate(shopId,dateTime);
    }

    /**
     * 统计新付费用户
     * @param shopId
     * @return
     */
    public int countNewPayUserNum(String shopId){
        return this.baseMapper.countNewPayUserNum(shopId);
    }

    /**
     * 统计老付费用户
     * @param shopId
     * @return
     */
    public int countOldPayUserNum(String shopId){
        return this.baseMapper.countOldPayUserNum(shopId);
    }

    /**
     * 会员等级编辑
     * @param params
     * @return
     */
    public boolean editUserLevel(SaveUserLevelParams params){
        try {
            UserLevel userLevel = ConvertUtils.sourceToTarget(params, UserLevel.class);
            return userLevelService.updateById(userLevel);
        } catch (Exception e) {
            log.info("会员等级编辑失败："+e.getMessage());
        }
        return false;
    }

    /**
     * 删除会员等级
     * @param levelId
     * @return
     */
    public boolean deleteUserLevel(String levelId){
        try {
            return this.removeById(levelId);
        } catch (Exception e) {
            log.info("删除会员等级失败："+e.getMessage());
        }
        return false;
    }
}